Skip to content

feat(flags): serve the typed record only for /flags?v=4 and name it v4 - #123366

Merged
trunk-io[bot] merged 1 commit into
masterfrom
feat/flags-v4-response-record
Oct 26, 2026
Merged

trunk-io[bot] merged 1 commit into
masterfrom
feat/flags-v4-response-record

Conversation

@andehen

@andehen andehen commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Problem

The flags service serves the typed flag record (key, value, reason, metadata, failed; no enabled/variant) for any non-/decide /flags request with v >= 3 while FLAGS_V3_RESPONSE_ENABLED is on. Clients already send v=3 and arbitrary v values to /flags (cache busters, typos, large numbers), so turning the setting on would hand those clients a record shape they cannot read. Only an exact v=4 should select the new record.

Changes

  • Selector. The typed record is served only when v parses to exactly 4 (serves_flags_v4). On the wire:
    • v=4 → typed record (setting on) or v2 record (setting off).
    • v=3, v>=5, cache-buster numbers that fit in an i32 → v2 record, setting on or off.
    • Values that do not parse as an i32 (4.0, 4.5, abc, numbers past i32) → legacy record, as today.
    • /decide (X-Original-Endpoint: decide) → unchanged; /decide?v=4 still gets the v2 record.
  • Rename to v4. The record is named after the request version that selects it: FlagsResponseV3/FlagDetailsV3/FlagDetailsMetadataV3 → …V4, ServiceResponse::V3 → V4, serves_flags_v3 → serves_flags_v4, the canonical-log response_format value FlagsV3 → FlagsV4, and tests/test_flags_v3.rs → tests/test_flags_v4.rs. Wire shape is unchanged.
  • Env var rename. FLAGS_V3_RESPONSE_ENABLED → FLAGS_V4_RESPONSE_ENABLED (config field flags_v4_response_enabled), default still false. No alias: the old variable is not set in any deployment. The setting still gates the record exactly as before.
  • The duplicated v.parse::<i32>().unwrap_or(1) is now one parse_version helper, so the unit test covers the real parse.
  • Doc comments and docs/internal/feature-flags/api-writes.md now say /flags?v=4.

The vendored harness contract under rust/feature-flags/tests/fixtures/rules_v2_contract (and the Python copy) is untouched. Its schemas are still named flags_response_v3*. A harness release renames them, and the next re-vendor picks that up. wire.rs notes the mismatch.

How did you test this code?

  • New rstest matrix test_only_an_exact_v4_selects_the_v4_record (unit, no DB): v=4 on/off, v=3 on/off, v=5, an 8-digit cache buster, v=2, v=4.0, a 44-digit number, abc, /decide with v=4 and v=3.
  • New integration test only_an_exact_v4_selects_the_v4_record covers the same cases over HTTP (POST and the GET minimal response). The existing v3 integration tests now request v=4. The setting-off test also covers v=3, v=4 and v=99.
  • Mutation check: putting back v >= 3 fails the new unit cases (v3, v5, cache buster) and the new integration test.
  • Locally, against isolated Postgres/Redis: cargo test -p feature-flags. Lib: 1959 passed. All integration binaries pass, except 3 test_flag_definitions dedicated-Redis tests that need a second Redis at the hard-coded localhost:6379, which was not running locally. cargo clippy -p feature-flags --all-targets -- -D warnings and cargo fmt --check are clean.

Rollback

Revert this PR. The setting defaults to off and is not set anywhere, so nothing on the wire changes until it is turned on.

🤖 Generated with Claude Code

Clients already send v=3 and arbitrary v values (cache busters, typos)
to /flags, so a v >= 3 selector would hand them a new record shape once
the setting is on. Only an exact v=4 now selects the typed record; every
other parsable version keeps the v2 record and an unparsable one keeps
the legacy record, as before. /decide is unchanged.

The record, its types and its setting are renamed after the request
version: FlagsResponseV4, FlagDetailsV4, serves_flags_v4, the FlagsV4
response_format log value, and FLAGS_V4_RESPONSE_ENABLED /
flags_v4_response_enabled (no alias; the old variable is not set
anywhere). The vendored harness contract still names its schemas
flags_response_v3* until the next harness release is vendored.
@trunk-io

trunk-io Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

😎 Merged successfully - details.

@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

✅ Trunk lane — non-backend lane (rust:crate:feature-flags)

This PR is assigned to the non-backend lane (rust:crate:feature-flags). It does not run backend Python tests and may merge in parallel with PRs in other lanes.

🚨 Comment density — 11% of added code lines are comments (22 of 198)

This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out.

Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See .agents/skills/writing-code-comments/SKILL.md for the house rules.

Files with the most added comment lines:

File Comment lines Added lines
rust/feature-flags/src/api/endpoint.rs 6 54
rust/feature-flags/src/api/types.rs 3 15
rust/feature-flags/src/handler/body_logger.rs 3 19
rust/feature-flags/src/flags/flag_matching.rs 2 2
rust/feature-flags/tests/test_rules_v2_evaluation/wire.rs 2 3
rust/feature-flags/src/config.rs 1 5
rust/feature-flags/src/flags/evaluate_v2.rs 1 1
rust/feature-flags/src/handler/canonical_log.rs 1 2

This check does not block merging. It updates on every push and clears when the share drops.

@trunk-io

trunk-io Bot commented Oct 26, 2026

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

View Full Report ↗︎ ⋅ Docs

@andehen
andehen marked this pull request as ready for review October 26, 2026 13:28
@parameterai

parameterai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Risk: No findings

This change narrows when the feature-flags service serves the typed flag record — only an exact v=4 with the new FLAGS_V4_RESPONSE_ENABLED setting on, instead of any v>=3 — and renames the V3 identifiers/env var to V4 with the wire shape unchanged. I found no security impact: version parsing is centralized so the served and body-logged records can never diverge, no auth or tenant-scoping code is touched, the default is off, and the stale-env-var failure direction is safely back to the old v2 shape.

Sentinel reviewed ce6a528 · Review settings

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested a review from a team October 26, 2026 13:29
@andehen andehen added the stamphog Request AI approval (no full review) label Oct 26, 2026
@posthog-project-board-bot posthog-project-board-bot Bot moved this to In Review in Feature Flags Oct 26, 2026

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved.

The public API change has unit and HTTP regression coverage, and the author's STRONG familiarity supplies the policy's assurance path despite cross-team ownership. No unresolved review concerns or other refusal grounds were found.

  • Author wrote 95% of the modified lines and has 15 merged PRs in these paths (familiarity STRONG).
Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✓ no deny categories matched
size ✓ 166L, 7F substantive, 315L/12F incl. docs/generated/snapshots — within ceiling
tier ✓ T1-agent / T1d-complex (315L, 12F, two-areas, feat)
stamphog 2.6.1 .stamphog/policy.yml @ ce6a528 · reviewed head ce6a528

@github-project-automation github-project-automation Bot moved this from In Review to Approved in Feature Flags Oct 26, 2026
@trunk-io
trunk-io Bot merged commit 430c108 into master Oct 26, 2026
290 checks passed
@trunk-io
trunk-io Bot deleted the feat/flags-v4-response-record branch October 26, 2026 14:02
@github-project-automation github-project-automation Bot moved this from Approved to Done in Feature Flags Oct 26, 2026
@deployment-status-posthog

deployment-status-posthog Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-10-26 14:37 UTC Run
prod-us ✅ Deployed 2026-10-26 14:58 UTC Run
prod-eu ✅ Deployed 2026-10-26 14:53 UTC Run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature/feature-flags Feature Tag: Feature flags stamphog Request AI approval (no full review) team/feature-flags

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant